//+------------------------------------------------------------------+
//|                                               TrendOscillationMA.mq5 |
//|                                      Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.metaquotes.net"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrRed,clrYellow,clrGreen     // 红色表示强趋势，黄色表示趋势减弱，绿色表示震荡
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

// 输入参数
input int    InpMAPeriod = 30;          // EMA周期
input int    InpADXPeriod = 14;         // ADX周期
input double InpADXThreshold = 20;       // ADX趋势阈值
input double InpSlopeThreshold = 2.0;    // 斜率阈值
input int    InpSlopeRegrPeriod = 5;    // 斜率计算周期
input int    InpConfirmPeriod = 2;      // 状态确认周期
input double InpTrendContinuityFactor = 0.7; // 趋势延续因子 (0.5-1.0)
input double InpWeakTrendThreshold = 0.5;    // 弱趋势阈值 (0.0-1.0)

// 指标缓冲区
double ExtMABuffer[];    // 均线值
double ExtColorBuffer[]; // 颜色索引
double ExtADXBuffer[];   // ADX值
double ExtSlopeBuffer[]; // 斜率值
double ExtTrendBuffer[]; // 趋势强度值
double ExtDIBuffer[];    // DI差值

// 全局变量
int    g_trend_count = 0;     // 趋势持续计数
int    g_non_trend_count = 0; // 震荡持续计数
bool   g_last_was_trend = false; // 上一状态是否为趋势
double g_last_trend_direction = 0; // 上一趋势方向
double g_prev_trend_strength = 0;  // 上一周期趋势强度

// 指标句柄
int    handle_ma;  // 均线指标句柄
int    handle_adx; // ADX指标句柄

//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
int OnInit()
{
    // 设置指标缓冲区
    SetIndexBuffer(0, ExtMABuffer, INDICATOR_DATA);
    SetIndexBuffer(1, ExtColorBuffer, INDICATOR_COLOR_INDEX);
    SetIndexBuffer(2, ExtADXBuffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, ExtSlopeBuffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(4, ExtTrendBuffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(5, ExtDIBuffer, INDICATOR_CALCULATIONS);
    
    // 设置指标属性
    PlotIndexSetString(0, PLOT_LABEL, "TrendOscillation MA");
    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpMAPeriod);
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
    
    // 设置指标精度
    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
    
    // 创建指标句柄
    handle_ma = iMA(_Symbol, PERIOD_CURRENT, InpMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
    handle_adx = iADX(_Symbol, PERIOD_CURRENT, InpADXPeriod);
    
    if(handle_ma == INVALID_HANDLE || handle_adx == INVALID_HANDLE)
    {
        Print("Error creating indicators");
        return(INIT_FAILED);
    }
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 自定义指标清理函数                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    if(handle_ma != INVALID_HANDLE)
        IndicatorRelease(handle_ma);
    if(handle_adx != INVALID_HANDLE)
        IndicatorRelease(handle_adx);
}

//+------------------------------------------------------------------+
//| 计算均线斜率                                                        |
//+------------------------------------------------------------------+
double CalculateSlope(const double &ma[], int position, int period)
{
    if(position < period) return 0.0;
    
    double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_x2 = 0.0;
    double first_value = ma[position - period + 1];
    
    for(int i = 0; i < period; i++)
    {
        double x = i;
        double y = (ma[position - i] - first_value) / _Point;
        
        sum_x += x;
        sum_y += y;
        sum_xy += x * y;
        sum_x2 += x * x;
    }
    
    double n = period;
    double slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
    
    return slope;
}

//+------------------------------------------------------------------+
//| 计算趋势强度                                                        |
//+------------------------------------------------------------------+
double CalculateTrendStrength(double adx, double slope, double ma_current, double ma_prev, double di_plus, double di_minus)
{
    double adx_factor = adx / 100.0;  // 归一化ADX (0-1)
    double slope_factor = MathMin(MathAbs(slope) / (InpSlopeThreshold * 2), 1.0);  // 归一化斜率
    double ma_change = MathAbs(ma_current - ma_prev) / _Point;
    double ma_factor = MathMin(ma_change / 10.0, 1.0);  // 归一化均线变化
    
    // 计算DI差值的影响
    double di_diff = MathAbs(di_plus - di_minus);
    double di_factor = di_diff / 100.0;
    
    // 计算趋势强度变化率
    double strength_change = 0;
    if(g_prev_trend_strength > 0)
    {
        strength_change = ((adx_factor + slope_factor + ma_factor) / 3.0 - g_prev_trend_strength) / g_prev_trend_strength;
    }
    
    // 根据趋势强度变化调整最终强度
    double base_strength = (adx_factor + slope_factor + ma_factor + di_factor) / 4.0;
    double final_strength = base_strength;
    
    // 如果趋势强度在减弱，加速降低强度值
    if(strength_change < 0)
    {
        final_strength *= (1.0 + strength_change);
    }
    
    return final_strength;  // 返回0-1之间的值
}

//+------------------------------------------------------------------+
//| 判断趋势状态                                                        |
//+------------------------------------------------------------------+
bool IsTrendState(double adx, double slope, double ma_current, double ma_prev, 
                 double di_plus, double di_minus, double &trend_strength, int &trend_state)
{
    // 计算趋势强度
    trend_strength = CalculateTrendStrength(adx, slope, ma_current, ma_prev, di_plus, di_minus);
    
    // 基本趋势条件
    bool strong_trend = adx > InpADXThreshold;
    bool significant_slope = MathAbs(slope) > InpSlopeThreshold;
    bool ma_direction = MathAbs(ma_current - ma_prev) > _Point;
    
    // 趋势方向
    double current_direction = ma_current > ma_prev ? 1 : -1;
    
    // 检查趋势是否减弱
    bool is_weakening = false;
    if(g_last_was_trend && trend_strength < g_prev_trend_strength)
    {
        double strength_drop = (g_prev_trend_strength - trend_strength) / g_prev_trend_strength;
        is_weakening = strength_drop > 0.2; // 如果强度下降超过20%
    }
    
    // 检查是否可能反转
    bool potential_reversal = false;
    if(g_last_was_trend && current_direction != g_last_trend_direction)
    {
        potential_reversal = true;
    }
    
    // 确定趋势状态
    if(strong_trend && significant_slope && ma_direction)
    {
        if(is_weakening || potential_reversal)
        {
            trend_state = 1; // 黄色，趋势减弱
        }
        else
        {
            trend_state = 0; // 红色，强趋势
        }
        return true;
    }
    else
    {
        trend_state = 2; // 绿色，震荡
        return false;
    }
}

//+------------------------------------------------------------------+
//| 自定义指标迭代函数                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    // 检查数据是否足够
    if(rates_total < InpMAPeriod + InpSlopeRegrPeriod) return(0);
    
    // 计算起始位置
    int start;
    if(prev_calculated == 0)
    {
        ArrayInitialize(ExtMABuffer, EMPTY_VALUE);
        ArrayInitialize(ExtColorBuffer, 2);
        ArrayInitialize(ExtADXBuffer, EMPTY_VALUE);
        ArrayInitialize(ExtSlopeBuffer, EMPTY_VALUE);
        ArrayInitialize(ExtTrendBuffer, EMPTY_VALUE);
        ArrayInitialize(ExtDIBuffer, EMPTY_VALUE);
        start = InpMAPeriod + InpSlopeRegrPeriod;
        g_trend_count = 0;
        g_non_trend_count = 0;
        g_last_was_trend = false;
        g_last_trend_direction = 0;
        g_prev_trend_strength = 0;
    }
    else
    {
        start = prev_calculated - 1;
    }
    
    // 复制指标数据
    if(CopyBuffer(handle_ma, 0, 0, rates_total, ExtMABuffer) <= 0) return(0);
    if(CopyBuffer(handle_adx, 0, 0, rates_total, ExtADXBuffer) <= 0) return(0);
    if(CopyBuffer(handle_adx, 1, 0, rates_total, ExtDIBuffer) <= 0) return(0);
    double di_minus[];
    if(CopyBuffer(handle_adx, 2, 0, rates_total, di_minus) <= 0) return(0);
    
    // 主计算循环
    for(int i = start; i < rates_total && !IsStopped(); i++)
    {
        // 计算斜率
        if(i >= InpSlopeRegrPeriod)
        {
            ExtSlopeBuffer[i] = CalculateSlope(ExtMABuffer, i, InpSlopeRegrPeriod);
            
            // 判断趋势状态
            double trend_strength;
            int trend_state;
            bool is_trend = IsTrendState(
                ExtADXBuffer[i],
                ExtSlopeBuffer[i],
                ExtMABuffer[i],
                ExtMABuffer[i-1],
                ExtDIBuffer[i],
                di_minus[i],
                trend_strength,
                trend_state
            );
            
            ExtTrendBuffer[i] = trend_strength;
            
            // 更新计数器
            if(is_trend)
            {
                g_trend_count++;
                g_non_trend_count = 0;
            }
            else
            {
                g_non_trend_count++;
                g_trend_count = 0;
            }
            
            // 更新状态
            if(g_trend_count >= InpConfirmPeriod)
            {
                g_last_was_trend = true;
            }
            else if(g_non_trend_count >= InpConfirmPeriod)
            {
                g_last_was_trend = false;
            }
            
            // 设置颜色
            ExtColorBuffer[i] = trend_state;
            
            // 更新上一周期的趋势强度
            g_prev_trend_strength = trend_strength;
            
            // 每500个柱子输出一次调试信息
            if(i % 500 == 0)
            {
                Print("Bar: ", i, " ADX: ", ExtADXBuffer[i], " Slope: ", ExtSlopeBuffer[i], 
                      " Trend Strength: ", trend_strength, " State: ", trend_state);
                Print("Bar: ", i, " Trend Count: ", g_trend_count, " Non-Trend Count: ", g_non_trend_count, 
                      " Last Was Trend: ", g_last_was_trend, " Direction: ", g_last_trend_direction);
            }
        }
        else
        {
            ExtColorBuffer[i] = 2; // 默认为震荡状态
        }
    }
    
    // 返回计算的K线数量
    return(rates_total);
} 